//go:build windows
// +build windows

package proxy

import (
	"bufio"
	"bytes"
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"io"
	"math/big"
	"net"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"regexp"
	"strings"
	"sync"
	"syscall"
	"time"
	"unsafe"
	D "websocket_apn/define"
	"websocket_apn/log"

	"golang.org/x/sys/windows"
	"golang.org/x/sys/windows/registry"
)

const (
	proxyAddress = "http=127.0.0.1:8888;https=127.0.0.1:8888"
)

var (
	// 目标 WebSocket 地址
	targetWebSocketHost = "proxy-xddq.hdnd01.com"
	// 自签名根证书
	rootCert     tls.Certificate
	rootPool     *x509.CertPool
	userInfo     D.UserInfo
	userInfoChan chan int
)

var FiddlerRootCrtData = `-----BEGIN CERTIFICATE-----
MIIDsjCCApqgAwIBAgIQVMfh0NGFIJNNtcrMQYDtWDANBgkqhkiG9w0BAQsFADBn
MSswKQYDVQQLDCJDcmVhdGVkIGJ5IGh0dHA6Ly93d3cuZmlkZGxlcjIuY29tMRUw
EwYDVQQKDAxET19OT1RfVFJVU1QxITAfBgNVBAMMGERPX05PVF9UUlVTVF9GaWRk
bGVyUm9vdDAeFw0yMTA3MjIwMTEwMzVaFw0yNzA3MjIwMTEwMzVaMGcxKzApBgNV
BAsMIkNyZWF0ZWQgYnkgaHR0cDovL3d3dy5maWRkbGVyMi5jb20xFTATBgNVBAoM
DERPX05PVF9UUlVTVDEhMB8GA1UEAwwYRE9fTk9UX1RSVVNUX0ZpZGRsZXJSb290
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2+rIrvmbbqJ0jG2Uk6nt
90sTt99/8NV5ISxWdUqSL8aItNsMoZsP18R2+8yBbRQSQilkdW93ctwAX2znVgzT
0WnpEIVBG6V9ROTD86qgmRiaScJkVm2IGdJgT7pHLZD1z6+VxEg7I9wCKby1Mvqo
GnpB+Bhe1746/qBk0vXl2mfVSCd/4brKaLZfM5pso1jrwF/jt4WbUW2PMy7g5+CJ
6DloON0yNI8TyUKH/FlaDJ9S2gALcVZAtxEYP2bYUffnthiA/PbOT7s1B7cj8/fP
wMSK3GOxv4AxWE3i7PhIpAsjiUK77cBpNYQyDoOZacR7cGrF0+o9hn4kVyotORvQ
jQIDAQABo1owWDATBgNVHSUEDDAKBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
AgEAMB0GA1UdDgQWBBQy9HpDXrCC3yD27YNJ0NGrFbSRlDAOBgNVHQ8BAf8EBAMC
AQYwDQYJKoZIhvcNAQELBQADggEBAA1SxU66evpXQb9j1Vs94h9JZdo+j9kBSPEv
f+A6Pxgl3wI9CaHAuptaO2ub/h7/K7dm+2nTnPoN1yi+zse27fg6lKEu5oihHfrK
vqo6a2bhp2gS+oqlRioCVvmpo7ROyR3ct4KkQ1m05JnRQI/BZNxZ6XebCmYubzP7
Vk0/KX0xj6bhQrD8duS5lM6tCoMcZqTT7DozXffZjwcFV/aYKdgEuUFT8LRLvqbz
CXNyVf5A2R1bb9C8P9vWSKx1dwbCMimUczxOCcneZX50c6l1rOGREzZTvqX1DE2q
cP+jYodWrzBGYkBjQuZDCvU+nKg4RRr0k3qFVNzh5UTnFgCq8vA=
-----END CERTIFICATE-----`

var rootCrtData = `-----BEGIN CERTIFICATE-----
MIIBnDCCASGgAwIBAgIQVMfh0NGFIJPNtcrMQYDtWDAKBggqhkjOPQQDAzAOMQww
CgYDVQQDEwNQUEgwIBcNMjQwMjIwMTU1NDMzWhgPMjExNTAxMzAxNTU0MzNaMA4x
DDAKBgNVBAMTA1BQSDB2MBAGByqGSM49AgEGBSuBBAAiA2IABCWV74rTJ/O2bh8/
unXDDUz6WlHjr862wPFnKojLptCwGpoyfYYmy1TjOou0GOn9HNyC60NUE2lwIhIa
HRbXfC2pNsaKEm3uxdRp7bkojzMGl5X3oOUpqX12+76o6Ma67KNCMEAwDgYDVR0P
AQH/BAQDAgGmMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFUGwICFNsGpymy3
Ka6FJi89XbXQMAoGCCqGSM49BAMDA2kAMGYCMQCsXARl4Yv/Q9PxchJJBJR/6Pmj
3sEY0zuVsdCJp1wBMMdf4Em7rZHR3IcOCfiJLq8CMQD3rBOkYf9EBNv2sT0aBHhF
HTcE6VuQ0Ak5Ma0WXd+ccNqnB2v0EXaUS+T3XZTzD10=
-----END CERTIFICATE-----`

var rootKeyData = `-----BEGIN RSA PRIVATE KEY-----
MIGkAgEBBDCAdlt3QCnBY2uT51YWEIHGsSNUBGxpWs1lR+M95ALCOtwzsgMIKUbt
cKEwI61lPTOgBwYFK4EEACKhZANiAAQlle+K0yfztm4fP7p1ww1M+lpR46/OtsDx
ZyqIy6bQsBqaMn2GJstU4zqLtBjp/RzcgutDVBNpcCISGh0W13wtqTbGihJt7sXU
ae25KI8zBpeV96DlKal9dvu+qOjGuuw=
-----END RSA PRIVATE KEY-----`

// 检查证书是否已安装
func checkCertificateInstalled(certData string) error {
	block, _ := pem.Decode([]byte(certData))
	if block == nil || block.Type != "CERTIFICATE" {
		return errors.New("failed to parse certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return err
	}

	store, err := windows.CertOpenStore(windows.CERT_STORE_PROV_SYSTEM, 0, 0, windows.CERT_SYSTEM_STORE_CURRENT_USER|windows.CERT_STORE_OPEN_EXISTING_FLAG, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("ROOT"))))
	if err != nil {
		return err
	}
	defer windows.CertCloseStore(store, 0)

	// 查找证书
	certContext, err := windows.CertFindCertificateInStore(store, windows.X509_ASN_ENCODING|windows.PKCS_7_ASN_ENCODING, 0, windows.CERT_FIND_SHA1_HASH, unsafe.Pointer(&cert.Raw[0]), nil)
	if certContext == nil {
		return errors.New("certificate not found")
	}

	return nil
}

// 安装证书
func installCertificate(certData string) error {
	block, _ := pem.Decode([]byte(certData))
	if block == nil || block.Type != "CERTIFICATE" {
		return errors.New("failed to parse certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return err
	}

	store, err := windows.CertOpenStore(windows.CERT_STORE_PROV_SYSTEM, 0, 0, windows.CERT_SYSTEM_STORE_CURRENT_USER|windows.CERT_STORE_OPEN_EXISTING_FLAG, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("ROOT"))))
	if err != nil {
		return err
	}
	defer windows.CertCloseStore(store, 0)

	// 导入证书
	certContext, err := windows.CertCreateCertificateContext(windows.X509_ASN_ENCODING|windows.PKCS_7_ASN_ENCODING, &cert.Raw[0], uint32(len(cert.Raw)))
	if err != nil {
		return err
	}
	defer windows.CertFreeCertificateContext(certContext)

	err = windows.CertAddCertificateContextToStore(store, certContext, windows.CERT_STORE_ADD_NEW, nil)
	if err != nil {
		return errors.New("failed to add certificate to store")
	}

	return nil
}

// 初始化
func initCert() {
	// 检查证书是否已安装
	if err := checkCertificateInstalled(rootCrtData); err != nil {
		if err := installCertificate(rootCrtData); err != nil {
			//log.Debugf("安装代理证书失败: %v", err)
		} else {
			log.Info("检测到代理证书未安装,开始为你安装")
		}
	} else {
		log.Infof("检测到代理证书已安装过")
	}
	var err error

	// 从变量加载自签名根证书和私钥
	rootCert, err = tls.X509KeyPair([]byte(rootCrtData), []byte(rootKeyData))
	if err != nil {
		log.Fatalf("Failed to load root certificate: %v", err)
	}

	// 创建根证书池
	rootPool = x509.NewCertPool()
	if !rootPool.AppendCertsFromPEM([]byte(rootCrtData)) {
		log.Errorf("Failed to add root certificate to pool")
	}
}

// 设置系统代理
func setSystemProxy(enable bool) error {
	// 打开注册表键
	key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.ALL_ACCESS)
	if err != nil {
		return fmt.Errorf("failed to open registry key: %v", err)
	}
	defer key.Close()

	// 设置代理地址
	if enable {
		if err := key.SetStringValue("ProxyOverride", "<-loopback>"); err != nil {
			return fmt.Errorf("failed to set ProxyServer: %v", err)
		}
		if err := key.SetStringValue("ProxyServer", proxyAddress); err != nil {
			return fmt.Errorf("failed to set ProxyServer: %v", err)
		}
		if err := key.SetDWordValue("ProxyEnable", 1); err != nil {
			return fmt.Errorf("failed to enable proxy: %v", err)
		}
		log.Warnf("已自动开启系统代理,代理规则 %s", proxyAddress)
		log.Warnf("开启本地端口8888的代理服务器,请打开微信登录游戏。")
	} else {
		if err := key.SetDWordValue("ProxyEnable", 0); err != nil {
			return fmt.Errorf("failed to disable proxy: %v", err)
		}
		log.Warnf("关闭系统代理")
	}

	// 通知系统设置已更改
	notifySystemProxyChange()
	return nil
}

// 通知系统代理设置已更改
func notifySystemProxyChange() {
	cmd := exec.Command("netsh", "winhttp", "import", "proxy", "source=ie")
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	if err := cmd.Run(); err != nil {
		//log.Errorf("Failed to notify system of proxy change: %v", err)
	}
}

// 启动透明代理
func StartTransparentProxy() D.UserInfo {
	// 设置系统代理
	if err := setSystemProxy(true); err != nil {
		log.Errorf("设置代理失败: %v", err)
	}
	// 关闭系统代理
	defer setSystemProxy(false)
	initCert()
	// 监听本地端口
	listener, err := net.Listen("tcp", ":8888")
	if err != nil {
		log.Errorf("启动端口8888的代理服务失败: %v", err)
	}
	userInfoChan = make(chan int, 1)
	// 捕获终止信号
	stopChan := make(chan os.Signal, 1)
	signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		select {
		case <-stopChan:
			log.Errorf("异常关闭代理服务")
			listener.Close()      // 关闭监听器
			setSystemProxy(false) // 关闭代理
		}
	}()
	go func() {
		for {
			// 接受客户端连接
			clientConn, err := listener.Accept()
			if err != nil {
				//log.Errorf("Failed to accept client connection: %v", err)
				continue
			}

			// 处理客户端连接
			go handleClientConnection(clientConn)
		}
	}()
	for {
		select {
		case <-userInfoChan:
			return userInfo
		}
	}
}

// 处理客户端连接
func handleClientConnection(clientConn net.Conn) {
	defer clientConn.Close()

	// 读取客户端请求的第一行（用于判断是否是 CONNECT 请求）
	reader := bufio.NewReader(clientConn)
	firstLine, err := reader.ReadString('\n')
	if err != nil {
		log.Errorf("Failed to read client request: %v", err)
		return
	}

	// 判断是否是 CONNECT 请求（HTTPS）
	if strings.HasPrefix(firstLine, "CONNECT") {
		handleHTTPSProxy(clientConn, reader, firstLine)
		return
	}
	// 判断是否是 HTTP 请求
	if strings.HasPrefix(firstLine, "GET") || strings.HasPrefix(firstLine, "POST") ||
		strings.HasPrefix(firstLine, "PUT") || strings.HasPrefix(firstLine, "DELETE") ||
		strings.HasPrefix(firstLine, "HEAD") || strings.HasPrefix(firstLine, "OPTIONS") ||
		strings.HasPrefix(firstLine, "PATCH") {
		forwardHTTPRequest(clientConn, reader, firstLine)
		return
	}

	// 如果不是 HTTP/HTTPS 请求，直接透明转发
	forwardAllRequest(clientConn, reader, firstLine)
}

// 动态生成证书
func generateCertificate(host string) (*tls.Certificate, error) {
	// 生成新的 RSA 密钥
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}

	// 创建证书模板
	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	serialNumber, err := rand.Int(rand.Reader, big.NewInt(1<<62))
	if err != nil {
		return nil, err
	}

	certTemplate := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"PPH"},
		},
		NotBefore:   notBefore,
		NotAfter:    notAfter,
		KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:    []string{host, "localhost", "127.0.0.1", "::1", "proxy-xddq.hdnd01.com"},
	}
	// 使用根证书创建 x509.Certificate 实例
	rootX509Cert, err := x509.ParseCertificate(rootCert.Certificate[0])
	if err != nil {
		return nil, err
	}
	// 生成证书
	certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTemplate, rootX509Cert, &priv.PublicKey, rootCert.PrivateKey)
	if err != nil {
		return nil, err
	}

	// 创建新的证书
	newCert := tls.Certificate{
		Certificate: [][]byte{certDERBytes},
		PrivateKey:  priv,
	}

	return &newCert, nil
}

// 处理 HTTPS 请求
func handleHTTPSProxy(clientConn net.Conn, reader *bufio.Reader, firstLine string) {
	// 解析 CONNECT 请求的目标地址
	parts := strings.Split(firstLine, " ")
	if len(parts) < 2 {
		log.Errorf("Invalid CONNECT request: %s", firstLine)
		return
	}
	targetAddr := parts[1]
	log.Debugf("HTTPS request, targetAddr: %s", targetAddr)
	// 响应客户端，隧道已建立
	_, err := clientConn.Write([]byte("HTTP/1.1 200 Connection Established\r\n\r\n"))
	if err != nil {
		log.Errorf("Failed to send connection established response: %v", err)
		return
	}

	if strings.Contains(firstLine, targetWebSocketHost) || strings.Contains(firstLine, "mysdk.37.com") || strings.Contains(firstLine, "fdes1.dttaa.cn") {
		// 使用自签名证书与客户端建立 TLS 连接
		clientTLSConn := tls.Server(clientConn, &tls.Config{
			Certificates: []tls.Certificate{rootCert},
			GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
				// 动态生成证书
				return generateCertificate(info.ServerName)
			},
		})
		if err := clientTLSConn.Handshake(); err != nil {
			//2025/02/13 15:22:13 Failed to connect to target server:x509: certificate signed by unknown authority
			log.Errorf("Failed to perform TLS handshake with client: %v", err)
			return
		}
		defer clientTLSConn.Close()

		// 与目标服务器建立 TLS 连接
		targetConn, err := tls.Dial("tcp", targetAddr, &tls.Config{
			InsecureSkipVerify: true, // 跳过证书验证,不关心目标服务器证书的有效性
			RootCAs:            rootPool,
		})
		if err != nil {
			log.Errorf("Failed to connect to target server: %v", err)
			return
		}
		defer targetConn.Close()

		// 转发数据并打印未加密内容
		go func() {
			buf := make([]byte, 4096)
			for {
				n, err := clientTLSConn.Read(buf)
				if err != nil {
					log.Errorf("Failed to read from client: %v", err)
					return
				}
				log.Debugf("Client -> Server (Hex): %s\n%s", hex.EncodeToString(buf[:n]), string(buf[:n]))
				targetConn.Write(buf[:n])
			}
		}()

		buf := make([]byte, 4096)
		for {
			n, err := targetConn.Read(buf)
			if err != nil {
				log.Debugf("Failed to read from server: %v", err)
				return
			}
			log.Debugf("Server -> Client (Hex): %s\n%s", hex.EncodeToString(buf[:n]), string(buf[:n]))
			// 检查是否包含特定数据
			if strings.Contains(string(buf[:n]), "playerId") || strings.Contains(string(buf[:n]), targetWebSocketHost) {
				re := regexp.MustCompile(`\{[.\W\w]*\}`)
				matches := re.FindString(string(buf[:n]))
				if matches != "" {
					err = json.Unmarshal([]byte(matches), &userInfo)
					if err == nil {
						userInfoChan <- 1
						return
					}
				}
			}
			clientTLSConn.Write(buf[:n])
		}
	} else {
		// 建立到目标服务器的连接
		targetConn, err := net.Dial("tcp", targetAddr)
		if err != nil {
			log.Errorf("Failed to connect to target server: %v", err)
			return
		}
		defer targetConn.Close()

		// 直接转发数据（不解析 HTTPS 内容）
		go io.Copy(targetConn, clientConn)
		io.Copy(clientConn, targetConn)
	}
}

// 转发HTTP请求
func forwardHTTPRequest(clientConn net.Conn, reader *bufio.Reader, firstLine string) {
	// 将 firstLine 和剩余的请求头数据合并
	// 这里读取 reader 缓存的内容
	remainingData, err := reader.Peek(reader.Buffered())
	if err != nil {
		log.Infof("Failed to read remaining data from reader: %v", err)
		return
	}

	// 创建新的请求内容，将 firstLine 和 remainingData 拼接
	newRequestData := append([]byte(firstLine), remainingData...)
	newReader := bufio.NewReader(bytes.NewReader(newRequestData))
	// 解析 HTTP 请求
	request, err := http.ReadRequest(newReader)
	if err != nil {
		log.Infof("Failed to parse HTTP request: %v firstLine: %s", err, firstLine)
		return
	}
	targetHost := request.Host
	if !strings.Contains(request.Host, ":") {
		targetHost += ":80"
	}
	log.Debugf("Http request addr: %s", request.Host)
	// 建立到目标服务器的连接
	targetConn, err := net.Dial("tcp", targetHost)
	if err != nil {
		log.Errorf("Failed to connect to target server: %v", err)
		clientConn.Close() // 关闭客户端连接，避免泄漏
		return
	}

	// 使用 context 控制资源释放
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // 确保最终释放资源

	// 启动监控 goroutine，在 context 取消时关闭双端连接
	go func() {
		<-ctx.Done()
		targetConn.Close()
		clientConn.Close()
	}()

	// 转发 HTTP 请求
	if err := request.Write(targetConn); err != nil {
		log.Errorf("Failed to forward HTTP request: %v", err)
		return
	}

	var wg sync.WaitGroup
	wg.Add(2)

	// 双方向数据转发
	copyAndClose := func(dst, src net.Conn) {
		defer wg.Done()
		io.Copy(dst, src) // 阻塞直到出错或 EOF
		cancel()          // 任一方向完成时触发资源释放
	}

	go copyAndClose(targetConn, clientConn)
	go copyAndClose(clientConn, targetConn)

	// 等待所有操作完成或 context 取消
	wg.Wait()
}

// 透明转发
func forwardAllRequest(clientConn net.Conn, reader *bufio.Reader, firstLine string) {
	log.Warnf("firstLine %s\n clientConn %+v", firstLine, clientConn)
	//// 建立到目标服务器的连接
	//targetConn, err := net.Dial("tcp", targetAddr)
	//if err != nil {
	//	log.Errorf("Failed to connect to target server: %v", err)
	//	return
	//}
	//defer targetConn.Close()
	//
	//// 使用 WaitGroup 等待两个方向的转发完成
	//var wg sync.WaitGroup
	//wg.Add(2)
	//
	//// 从客户端转发数据到目标服务器
	//go func() {
	//	defer wg.Done()
	//	_, err := io.Copy(targetConn, clientConn)
	//	if err != nil {
	//		log.Errorf("Failed to forward data to target server: %v", err)
	//	}
	//}()
	//
	//// 从目标服务器转发数据到客户端
	//go func() {
	//	defer wg.Done()
	//	_, err := io.Copy(clientConn, targetConn)
	//	if err != nil {
	//		log.Errorf("Failed to forward data to client: %v", err)
	//	}
	//}()
	//
	//// 等待两个方向的转发完成
	//wg.Wait()
}
